package level.editor.view.desktop;

import java.awt.Color;
import java.awt.Component;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
import java.beans.PropertyVetoException;
import java.util.ArrayList;

import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JDesktopPane;
import javax.swing.JInternalFrame;
import javax.swing.KeyStroke;

import level.editor.control.main.MainTabbed;
import level.editor.view.Window;
import level.editor.view.action.edit.RedoAction;
import level.editor.view.action.edit.UndoAction;
import level.editor.view.action.file.CloseAction;
import level.editor.view.action.file.NewAction;
import level.editor.view.action.file.OpenAction;
import level.editor.view.action.file.SaveAction;
import level.editor.view.action.file.SaveAsAction;
import level.editor.view.action.frame.AddCollisionControlAction;
import level.editor.view.action.frame.AddLayerControlAction;
import level.editor.view.action.frame.AddObjectControlAction;
import level.editor.view.action.frame.AddTileControlAction;
import level.editor.view.base.BasePanel;
import level.editor.view.frame.InternalFrame;
import level.editor.view.group.Group;
import level.editor.view.group.Item;

public class Desktop extends JDesktopPane
{
	public Desktop(Window window)
	{
		init(window);
		initActions();
	}

	public void repaint()
	{
		super.repaint();
		if (base != null)
			base.updateBasePanel(this.getSize());
		if (outline != null)
			outline.updateOutlinePanel(this.getSize());
	}

	public ArrayList<AbstractAction> getActions()
	{
		return actions;
	}

	public BasePanel getBasePanel()
	{
		return base;
	}

	public boolean hasControl(String name)
	{
		// Search for all names inside of each frame, and then search the side
		// panels
		for (Component comp : this.getComponents())
		{
			if (comp instanceof InternalFrame
					&& ((InternalFrame) comp).getTitle() != null)
			{
				if (((InternalFrame) comp).getTitle().equals(name))
					return true;
			}
		}
		return false;
	}

	public void setRectangle(Rectangle rect, boolean newType)
	{
		if (rect == null)
			outline.setVisible(false);
		else
		{
			outline.setVisible(true);
			if (base.hasLeft() && !newType && rect.getX() < 5)
				rect.setBounds(base.getLeft().getBounds());
			else if (base.hasRight() && !newType && rect.getX() > 5)
			{
				rect.setBounds(base.getRight().getBounds());
				if (base.hasLeft() && !base.hasRight())
					rect.setLocation(
							((int) rect.getX() + base.getLeft().getWidth()
									+ base.getLeft().getX() + 2),
							(int) rect.getY());
			}

			else if (base.hasLeft() && newType)
				rect.setLocation((int) (rect.getX() + base.getLeft().getWidth()
						+ 5 - rect.getWidth() / 2), (int) rect.getY());
			else if (newType)
				rect.setLocation((int) (rect.getX() - rect.getWidth() / 2),
						(int) rect.getY());

		}
		outline.setRectangle(rect);
		outline.repaint();
	}

	public void addFrameFromTab(Item item, Rectangle bounds)
	{
		InternalFrame frame = new InternalFrame(item.getName(), item.getIcon());
		frame.addItem(item);
		frame.setBounds(bounds);
		if (base.hasLeft())
		{
			frame.setLocation((int) (frame.getX() + base.getLeft().getWidth()
					+ 5 - frame.getWidth() / 2), (int) frame.getY());
		}
		else
		{
			frame.setLocation((int) (frame.getX() - frame.getWidth() / 2),
					(int) frame.getY());
		}
		add(frame, InternalFrame.Z_ORDER);
		frame.moveToFront();
		try
		{
			frame.setSelected(true);
		}
		catch (PropertyVetoException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		revalidate();
	}

	public ArrayList<Group> getGroups()
	{
		ArrayList<Group> groups = new ArrayList<Group>();
		for (JInternalFrame f : getAllFrames())
		{
			if (f instanceof InternalFrame)
			{
				InternalFrame frame = (InternalFrame) f;
				if (!frame.isIcon())
				{
					groups.add((Group) frame.getContentPane());
				}
			}

		}

		return groups;
	}

	public MainTabbed getMainTabbed()
	{
		return base.getMainTabbed();
	}

	@Override
	public void add(Component comp, Object constraints)
	{
		super.add(comp, constraints);
		if (comp instanceof InternalFrame)
		{
			InternalFrame frame = (InternalFrame) comp;
			if (frame.getOrigin() != null)
				frame.setLocation(frame.getOrigin());
		}
	}

	private void init(Window window)
	{
		setDesktopManager(new DesktopManager());
		// setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);
		setSize(window.getContentPane().getSize());
		setBackground(Color.gray);
		outline = new DesktopOutlinePane();
		add(outline, DesktopOutlinePane.Z_ORDER);
		outline.setVisible(false);
		add(base = new BasePanel(this), BasePanel.Z_ORDER);
		base.initDefaultHandler(window);
		revalidate();
		// Redo this later
		// base = new BasePanel(this);
		// add(base, BasePanel.Z_ORDER);
		// revalidate();
	}

	private void initActions()
	{
		actions = new ArrayList<AbstractAction>();
		MainTabbed tabbed = getMainTabbed();

		AddTileControlAction tile = new AddTileControlAction(this);
		AddLayerControlAction layer = new AddLayerControlAction(this);
		AddCollisionControlAction collision = new AddCollisionControlAction(
				this);
		AddObjectControlAction object = new AddObjectControlAction(this);
		NewAction newAction = new NewAction(tabbed);
		SaveAction save = new SaveAction(tabbed);
		SaveAsAction saveAs = new SaveAsAction(tabbed);
		OpenAction open = new OpenAction(tabbed);
		CloseAction close = new CloseAction(tabbed);
		UndoAction undo = new UndoAction(tabbed);
		RedoAction redo = new RedoAction(tabbed);

		actions.add(newAction);
		actions.add(open);
		actions.add(save);
		actions.add(saveAs);
		actions.add(close);
		actions.add(undo);
		actions.add(redo);
		actions.add(tile);
		actions.add(layer);
		actions.add(collision);
		actions.add(object);

		InputMap iMap = this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
		ActionMap aMap = this.getActionMap();

		iMap.put(
				KeyStroke.getKeyStroke(KeyEvent.VK_T, KeyEvent.CTRL_DOWN_MASK),
				"NEW_TILE_WINDOW");
		aMap.put("NEW_TILE_WINDOW", tile);

		iMap.put(
				KeyStroke.getKeyStroke(KeyEvent.VK_R, KeyEvent.CTRL_DOWN_MASK),
				"NEW_LAYER_WINDOW");
		aMap.put("NEW_LAYER_WINDOW", layer);

		iMap.put(
				KeyStroke.getKeyStroke(KeyEvent.VK_E, KeyEvent.CTRL_DOWN_MASK),
				"NEW_COLLISION_WINDOW");
		aMap.put("NEW_COLLISION_WINDOW", collision);

		iMap.put(
				KeyStroke.getKeyStroke(KeyEvent.VK_G, KeyEvent.CTRL_DOWN_MASK),
				"NEW_OBJECT_WINDOW");
		aMap.put("NEW_OBJECT_WINDOW", object);
		
		iMap.put(
				KeyStroke.getKeyStroke(KeyEvent.VK_N, KeyEvent.CTRL_DOWN_MASK),
				"NEW_FILE");
		aMap.put("NEW_FILE", newAction);

		iMap.put(
				KeyStroke.getKeyStroke(KeyEvent.VK_S, KeyEvent.CTRL_DOWN_MASK),
				"SAVE_FILE");
		aMap.put("SAVE_FILE", save);

		iMap.put(
				KeyStroke.getKeyStroke(KeyEvent.VK_S, KeyEvent.CTRL_DOWN_MASK
						+ KeyEvent.SHIFT_DOWN_MASK), "SAVE_AS_FILE");
		aMap.put("SAVE_AS_FILE", saveAs);

		iMap.put(
				KeyStroke.getKeyStroke(KeyEvent.VK_O, KeyEvent.CTRL_DOWN_MASK),
				"OPEN_FILE");
		aMap.put("OPEN_FILE", open);

		iMap.put(
				KeyStroke.getKeyStroke(KeyEvent.VK_W, KeyEvent.CTRL_DOWN_MASK),
				"CLOSE_FILE");
		aMap.put("CLOSE_FILE", close);

		iMap.put(
				KeyStroke.getKeyStroke(KeyEvent.VK_Z, KeyEvent.CTRL_DOWN_MASK),
				"UNDO_ACTION");
		aMap.put("UNDO_ACTION", undo);

		iMap.put(
				KeyStroke.getKeyStroke(KeyEvent.VK_Y, KeyEvent.CTRL_DOWN_MASK),
				"REDO_ACTION");
		aMap.put("REDO_ACTION", redo);
	}

	private ArrayList<AbstractAction> actions;
	private BasePanel base;
	private DesktopOutlinePane outline;
}
